fix(perf): correct INLINE_BACKFILL_THRESHOLD docstring and raise threshold#1492
Conversation
… diff Adds snapshot-pre-bash.sh (PreToolUse Bash) + track-bash-writes.sh (PostToolUse Bash): the pre-hook captures git status --porcelain to a per-worktree temp file before each Bash call; the post-hook diffs the before/after state and appends newly modified or created files to .claude/session-edits.log. This closes the gap where files written by sed -i, printf redirects, tee, heredocs, or build tools (Cargo.lock, lockfiles) were never recorded, causing guard-git.sh to emit false-positive BLOCKED errors. Closes #1457
- clojure.rs: annotate lifetime-anchor assignment to silence false-positive - cfg.rs: remove never-called start_line_of method - complexity.rs: remove never-constructed NotHandled variant; convert irrefutable if-let patterns to plain let destructures - dataflow.rs: remove never-read callee fields from CallReturn/Destructured - incremental.rs: remove never-read lang field from CacheEntry cargo check and cargo clippy both clean after these changes.
Adds .github/workflows/perf-canary.yml — a path-filtered workflow that fires on PRs touching src/extractors/, src/domain/graph/, or crates/** and runs only the incremental-benchmark suite (full build + no-op + 1-file rebuild, both engines). Catches the class of regressions that accumulated invisibly across the Phase 8.x PRs and were only detected at v3.12.0 publish time. The regression guard gains BENCH_CANARY=1 mode: raises thresholds to 50%/100%/150% (standard/noisy/WASM) and skips the build, query, and resolution suites — only incremental checks run. This absorbs shared- runner timing variance while still blocking catastrophic regressions (+98% full build, +1827% 1-file rebuild from v3.12.0). Closes #1433
On incremental builds, runPostNativeCha previously scanned all call→qualified-method edges in the DB (~12ms flat, O(graph size)), even for 1-file changes where no hierarchy or RTA evidence changed. Add two cheap indexed gate queries. Gate A checks whether any changed file introduced a class/interface/trait/struct/record node (hierarchy may have new implementors reachable from unchanged call sites). Gate B checks whether any changed file added a call edge to a class-kind target (RTA set may have grown, enabling previously filtered expansions in unchanged callers). If neither gate fires, restrict the candidate query to src.file IN changedFiles — safe because the hierarchy and instantiated set are unchanged for all other files. Full builds (isFullBuild=true) and cases where either gate fires retain the existing full-scan behaviour. Mirrors the changed-files scoping pattern of runPostNativeThisDispatch. Closes #1441
Times each JS post-pass in tryNativeOrchestrator and exposes the
measurements in BuildResult.phases:
- gapDetectMs — dropped-language gap detection + backfill
- chaMs — CHA expansion (interface dispatch)
- thisDispatchMs — this/super dispatch WASM re-parse (was already
tracked but now properly named alongside the rest)
- reclassifyMs — scoped role re-classification after edge insertion
- techniqueBackfillMs — technique-column UPDATE on native-written edges
Previously only thisDispatchMs was reported, causing wall-clock vs
phaseSum to diverge by 1.1s+ on 1-file rebuilds and making benchmark
regressions undiagnosable from committed history.
Updates update-incremental-report.ts to render the new phases in a
collapsible details block under each engine's 1-file rebuild section.
Closes #1434
…ld for required-tier grammars The docstring claimed pool cost was "amortised over enough parse work" — measurements show IPC overhead scales linearly (~55–64ms/file pool vs ~8–10ms/file inline). The real motivation is crash safety for exotic WASM grammars (#965); JS/TS/TSX (required-tier, used in all this-dispatch backfill calls) have never triggered the V8 fatal crash class and are safe to run inline. Raise threshold 16 → 32 to keep typical this-dispatch batches (≤ 18 files on the codegraph corpus) on the inline fast path. Exotic-language drops are almost always well under 32 files and also benefit from the inline path without meaningful crash risk increase. Closes #1435
|
Claude finished @carlos-alm's task —— View job PR Review
Phase 1: Root Cause AnalysisProblem Being Solved: The Why This Approach: Two orthogonal fixes in one minimal change — (1) raise the threshold past the measured batch size of 18, and (2) correct the misleading docstring to accurately explain the crash-safety rationale (not cost amortisation). The threshold of 32 gives headroom over 18 while still routing truly large batches through the pool. Risk Assessment: Low. JS/TS/TSX are required-tier grammars with no history of the V8 fatal crash class. Raising the inline ceiling to 32 from 16 for files that call Phase 2: Configuration Change DetectionNo linting rules, test timeouts, or build configuration were changed. The only constant modified is Phase 3: Test IntegrityNo tests were modified. There are no direct unit tests for Minor observation: the threshold is a magic constant with no test asserting the inline path is taken for expected batch sizes. This isn't a blocker, but a test that exercises Phase 4: Code QualityDocstring correctness (
Threshold value ( Secondary docstring ( No bugs, security issues, or architectural concerns introduced. Phase 5: Backlog Compliance
Final Assessment |
Greptile SummaryThis PR corrects the
Confidence Score: 5/5Safe to merge — the threshold change is a well-measured constant bump, and the native-orchestrator logic simplifications are guarded by the function's own early-return. The threshold raise is backed by concrete measurements and narrows crash risk minimally (JS/TS/TSX have never triggered the V8 fatal class). The backfill-condition simplification is safe because No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[parseFilesWasmForBackfill\ncalled with N files] --> B{N ≤ INLINE_BACKFILL_THRESHOLD\nnow 32, was 16}
B -- yes\nJS/TS/TSX this-dispatch\nbatches ≤18 files --> C[parseFilesWasmInline\nmain-thread ~8–10ms/file]
B -- no\nlarge or exotic-language drops --> D[parseFilesWasm via worker pool\ncrash-isolated ~55–64ms/file]
C --> E[Return results]
D --> E
subgraph native-orchestrator fast paths
F[detectDroppedLanguageGap] --> G{gap empty?}
G -- yes --> H[Skip backfillNativeDroppedFiles]
G -- no --> I[backfillNativeDroppedFiles\nwrites nodes+edges]
I --> J{postPassWroteData?\nbackfill OR CHA edges\nOR this-dispatch targets}
J -- no --> K[Skip COUNT star scan\nRust counts still accurate]
J -- yes --> L[COUNT star re-count\nupdate build_meta]
end
Reviews (5): Last reviewed commit: "fix(perf): guard post-native passes on 1..." | Re-trigger Greptile |
…nce threshold constant
The secondary docstring still described the old 16-value rationale
("engine-parity drop sizes"). Replace with a pointer to
INLINE_BACKFILL_THRESHOLD where the full rationale now lives.
|
Fixed — updated the stale |
docs check acknowledged — merge resolution only; no new features or API changes to document
…1493) * fix(perf): guard post-native passes against unnecessary work on 1-file incremental rebuilds On 1-file native incremental builds, two JS post-passes ran unconditionally even when they had no work to do: - `backfillNativeDroppedFiles`: called whenever changedCount > 0, even when detectDroppedLanguageGap returned an empty gap. Gate now checks gap.missingAbs.length > 0 || gap.staleRel.length > 0 directly, matching backfillNativeDroppedFiles's own internal early-exit guard. - Node/edge COUNT(*) re-count: ran unconditionally after all post-passes even when none of them wrote any edges. COUNT(*) over 50K+ edge tables is non-trivial, especially via the NativeDbProxy napi-rs round-trip. Now gated on postPassWroteData (backfill | CHA edges | this-dispatch edges). Closes #1454 * refactor(perf): hoist backfillHappened before if to avoid duplicate expression Greptile suggested hoisting the backfillHappened variable declaration above the conditional that guards backfillNativeDroppedFiles, so the boolean expression is written exactly once. Previously the condition was evaluated in both the if-guard and the const declaration on the following line.
Codegraph Impact Analysis1 functions changed → 5 callers affected across 5 files
|
The
INLINE_BACKFILL_THRESHOLDdocstring claimed pool cost was "amortised over enough parse work" — measurements show IPC overhead scales linearly (~55–64ms/file pool vs ~8–10ms/file inline). The real motivation is grammar-crash safety for exotic parsers (#965); JS/TS/TSX (required-tier, used in all this-dispatch backfill calls) have never triggered the V8 fatal crash class and are safe to run inline.Changes
Why 32
The primary hot caller (
runPostNativeThisDispatch) measured 18 JS/TS files at 55–64ms/file through the pool vs 8–10ms/file inline — a 3–6x penalty. Raising to 32 covers that batch with headroom. Anything larger (truly exotic-language drops at scale) still routes through the pool for crash isolation.Closes #1435